const reqlib = require('app-root-path').require
const btbAs = reqlib('/app/common/btb')
const timeConst = reqlib('/app/const/time')
const quantityUtilHY = reqlib('/app/common/btb/quantityUtilHY')
const binanceProxy = reqlib('/app/common/binanceProxy')
const buyFunc = require('./buySellSub/buy')
const sellFunc = require('./buySellSub/sell')
const pingDuoFunc = require('./buySellSub/pingDuo')
const pingKongFunc = require('./buySellSub/pingKong')
const noSellFunc = require('./buySellSub/noSell')
const noBuyFunc = require('./buySellSub/noBuy')
const addPoolFunc = require('./buySellSub/addPool')
const strategyFunc = require('./utils/strategy')
const analysisFindFunc = require('./buySellSub/analysisFind')
const combinedIndicatorFunc = require('./utils/combinedIndicator')
const tradeRecordFunc = require('./utils/tradeRecord')
const utilBuySellFunc = require('./utils/utilBuySell')
const indexFlagFunc = require('./utils/indexFlag')
const noPingDuoFunc = require('./buySellSub/noPingDuo')
const noPingKongFunc = require('./buySellSub/noPingKong')
const specialMarketFunc = require('./buySellSub/specialMarket')
const sellReasonFunc = require('./buySellSub/sellReason')
const pingKongReasonFunc = require('./buySellSub/pingKongReason')
const sellReverseFunc = require('./buySellSub/sellReverse')
const buyReasonFunc = require('./buySellSub/buyReason')
const buyReverseFunc = require('./buySellSub/buyReverse')
const buyPreReverseFunc = require('./buySellSub/buyPreReverse')
const buyPrePositiveFunc = require('./buySellSub/buyPrePositive')
const sellPreReverseFunc = require('./buySellSub/sellPreReverse')
const sellPrePositiveFunc = require('./buySellSub/sellPrePositive')
const utilReasonFunc = require('./utils/utilReason')
const MarketMachine = require('./marketMachine')
const numberUtil = reqlib('/app/util/numberUtil')

function BuySellMachine (config) {
  this.tradeTime15mCycle = btbAs.get15mTradeTimeCycle()
  this.tradeTime = btbAs.getTradeTimeHm()
  // 中国的切换
  this.isDayChangeTime = ['23:30', '23:45', '24:00', '00:00', '00:15', '00:30'].indexOf(this.tradeTime) !== -1
  // 美国的切换
  this.isUSDayChangeTime = ['08:00', '08:15'].indexOf(this.tradeTime) !== -1
  this.is4hLastTime = ['00:00', '04:00', '08:00', '12:00', '16:00', '20:00', '24:00'].indexOf(this.tradeTime) !== -1
  this.is4hImportantChangeTime = [
    '23:45', '24:00', '00:00', '00:15',
    '07:45', '08:00', '08:15',
    '11:45', '12:00', '12:15',
    '19:45', '20:00', '20:15'
  ].indexOf(this.tradeTime) !== -1
  this.is4hChangeTime = [
    '23:45', '24:00', '00:00', '00:15',
    '03:45', '04:00', '04:15',
    '07:45', '08:00', '08:15',
    '11:45', '12:00', '12:15',
    '15:45', '16:00', '16:15',
    '19:45', '20:00', '20:15'
  ].indexOf(this.tradeTime) !== -1
  this.is4hLargeChangeTime = [
    '23:30', '23:45', '24:00', '00:00', '00:15', '00:30',
    '03:30', '03:45', '04:00', '04:15', '04:30',
    '07:30', '07:45', '08:00', '08:15', '08:30',
    '11:30', '11:45', '12:00', '12:15', '12:30',
    '15:30', '15:45', '16:00', '16:15', '16:30',
    '19:30', '19:45', '20:00', '20:15', '20:30'
  ].indexOf(this.tradeTime) !== -1
  this.tradeTime4hCycle = timeConst.time15mList.indexOf(this.tradeTime) % 16
  this.realBuySell = config.realBuySell || false
  this.preFind = config.preFind || false
  this.BtbIndexProxy = config.BtbIndexProxy
  this.btbItem = config.btbItem
  this.btbItem.buy_sell_reason = this.btbItem.buy_sell_reason || ''
  this.btbLeverage = config.btbItem.leverage || 1
  this.btbReasonList = this.btbItem.reason_list || []
  this.marketInfo = false
  this.marketFlagInfo = {}
  this.marketMachine = {}
  this.marketInfoList = config.marketInfoList || []
  if (config.marketInfo && Object.keys(config.marketInfo).length > 0) {
    this.marketInfo = config.marketInfo
    this.marketMachine = new MarketMachine({
      marketInfo: this.marketInfo,
      marketInfoList: this.marketInfoList
    })
    this.marketFlagInfo = this.marketMachine.getAllFlag()
  }
  this.futuresAccount = {}
  this.symbolAccount = {}
  this.beforeSymbolAccount = {}
  this.btbItem.usdt = 0
  this.directionLevel = this.btbItem.direction_level || 0
  this.directionType = this.btbItem.direction || ''
  this.hasPosition = false
  this.hasDuoPosition = false
  this.hasKongPosition = false
  this.resetAccount(config)
  this.analysisInfoFlag15m = this.btbItem.analysisInfoFlag15m || {}
  this.analysisInfoFlag1h = this.btbItem.analysisInfoFlag1h || {}
  this.analysisInfoFlag4h = this.btbItem.analysisInfoFlag4h || {}
  this.analysisInfoFlag1d = this.btbItem.analysisInfoFlag1d || {}
  this.upDownDaysInfo15m = this.analysisInfoFlag15m.upDownDaysInfo || {}
  this.upDownDaysInfo1h = this.analysisInfoFlag1h.upDownDaysInfo || {}
  this.upDownDaysInfo4h = this.analysisInfoFlag4h.upDownDaysInfo || {}
  this.upDownDaysInfo1d = this.analysisInfoFlag1d.upDownDaysInfo || {}
  this.lastEmaInfo15m = this.analysisInfoFlag15m.lastEmaInfo || {}
  this.lastEmaInfo1h = this.analysisInfoFlag1h.lastEmaInfo || {}
  this.lastEmaInfoh = this.analysisInfoFlag4h.lastEmaInfo || {}
  this.lastEmaInfo1d = this.analysisInfoFlag1d.lastEmaInfo || {}
  // 核心
  this.analysisInfo15m = this.analysisInfoFlag15m.flagInfo || {}
  this.analysisInfo1h = this.analysisInfoFlag1h.flagInfo || {}
  this.analysisInfo4h = this.analysisInfoFlag4h.flagInfo || {}
  this.analysisInfo1d = this.analysisInfoFlag1d.flagInfo || {}
  this.nowEmaInfo15m = this.analysisInfoFlag15m.nowEmaInfo || {}
  this.nowEmaInfo1h = this.analysisInfoFlag1h.nowEmaInfo || {}
  this.nowEmaInfo4h = this.analysisInfoFlag4h.nowEmaInfo || {}
  this.nowEmaInfo1d = this.analysisInfoFlag1d.nowEmaInfo || {}
  this.btbItem.close = this.nowEmaInfo15m.close
  // 标志
  // 策略，正着做，反着做
  this.strategy = '1'
  this.strategyResult = ''
  this.manual = this.btbItem.manual || 0
  // 根据最原始的总仓位进行操作
  this.buySellRawTotalWalletBalance = false
  // 最大仓，(虽然风险大，但是你想想，很多很平庸的机会你都给1/10的仓位了，仅仅因为信号少)
  this.useMaxIndexBuySellPosition = false
  // 手动修改仓位
  this.minPositionConfig = 0
  this.coverPositionConfig = 0
  this.stopProfitPrice = 0
  this.addPool = false
  this.tradeReason = ''
  this.buy = false
  this.buyReason = ''
  this.sell = false
  this.sellReason = ''
  this.pingKong = false
  this.pingKongReason = ''
  this.pingDuo = false
  this.pingDuoReason = ''
  this.ifOnlyPingKongByReason = this.initIfOnlyPingKongByReason()
  this.ifOnlyPingDuoByReason = this.initIfOnlyPingDuoByReason()
  this.ifSellReverseTrend = this.initIfSellReverseTrend()
  this.ifSellPreReverseTrend = this.initIfSellPreReverseTrend()
  this.ifSellPrePositiveTrend = this.initIfSellPrePositiveTrend()
  this.ifBuyReverseTrend = this.initIfBuyReverseTrend()
  this.ifBuyPreReverseTrend = this.initIfBuyPreReverseTrend()
  this.ifBuyPrePositiveTrend = this.initIfBuyPrePositiveTrend()
  this.ifCanIgnoreNobuy = false
  this.ifCanIgnoreNoSell = false
  this.buyRate = 0
  this.sellRate = 0
  this.pingDuoRate = 0
  this.pingKongRate = 0
  this.buySellPriority = 0
  this.trackList = []
  this.errorTrackList = []
  this.stopClose = 0
  // 只对当前负责
  this.ifPingNextKlineLocal = false
  this.ifPingNext1hKlineLocal = false
  this.requestOrderId = ''
  // 最终的操作类型
  this.requestBuySellType = ''
  this.btbModelUpdateParams = {}
  this.indexFlagInfo = this.getAllIndexFlag()
}

BuySellMachine.prototype = {
  getPreInfo () {
    return {
      buy: this.buy,
      sell: this.sell,
      addPool: this.addPool,
      buySellPriority: this.buySellPriority
    }
  },
  getIfAddInPollResult () {
    const preInfo = this.getPreInfo()
    for (let key in preInfo) {
      if (preInfo[key]) {
        return true
      }
    }
    return false
  },
  pushError (err) {
    this.errorTrackList.push(err.msg || err.message)
  },
  setStrategy (val, text) {
    this.strategy = val || '1'
    this.strategyResult = text || ''
  },
  setBuySellStrategy () {
    if (!this.marketInfo) {
      // 数据太少的不做
      return
    }
    if (this.ifSellPreReverseTrend || this.ifSellReverseTrend) {
      this.setStrategy('2', 'sr-1')
      return
    }
    if (this.ifBuyPreReverseTrend || this.ifBuyReverseTrend) {
      this.setStrategy('2', 'br-1')
      return
    }
    if (this.ifSellPrePositiveTrend) {
      this.setStrategy('1', 'sp-1')
      return
    }
    if (this.ifBuyPrePositiveTrend) {
      this.setStrategy('1', 'bp-1')
      return
    }
    if (this.setStrategyBySpecialMarket()) {
      return
    }
    if (this.setStrategyByNewUpDown()) {
      return
    }
    if (this.setStrategyByNewHighLow()) {
      return
    }
    if (this.setStrategyByBeforeConfig()) {
      return
    }
    if (this.setForwardStrategyByKdjKeepManyDays()) {
      return
    }
    if (this.setForwardStrategyByEmaShuttle()) {
      return
    }
    if (this.setForwardStrategyByMarketResonance()) {
      return
    }
    if (this.setForwardStrategyBySpecialAnalysis()) {
      return
    }
    if (this.setForwardStrategyByItemTrend()) {
      return
    }
    if (this.setStrategyBySpecialMarketTrend()) {
      return
    }
    this.setStrategy('2', 's-12')
  },
  execute () {
    if (!this.marketInfo || !this.analysisInfo4h.hasFullData) {
      // 数据太少的不做
      this.setNoExecuteRaw('noExecute-1')
      return
    }
    // 设置方向
    this.setBuySellStrategy()
    if (!(this.ifOnlyPingKongByReason || this.ifOnlyPingDuoByReason)) {
      // 多方向
      this.buyIfHighFrequency()
      this.buyIfAttack15m()
      this.buyIfMacdUpManyDays()
      this.buyIfEmaUpManyDays()
      // 空方向
      this.sellIfHighFrequency()
      this.sellIfCrash15m()
      this.sellIfMacdDownManyDays()
      this.sellIfEmaDownManyDays()
      this.sellIfUpManyDaysTransDown()
      this.sellIfMarket()
      // 定制方向的
      this.buyIfPositivePreTrend()
      this.buyIfReversePreTrend()
      this.sellIfPositivePreTrend()
      this.sellIfReversePreTrend()
      // 优先级比较高，仅次于reason
      this.buyIfReverseTrend()
      this.sellIfReverseTrend()
    }
    // 最高优先级，本质上是reason了
    this.buyIfStepBack()
    this.sellIfStepBack()
    this.sellIfOnlyPingByReason()
    this.buyIfOnlyPingByReason()
    // 限制
    if (this.ifOnlyPingKongByReason || this.ifOnlyPingDuoByReason) {
      // 只限制平仓的逻辑，如果另外开仓了，那另说
      if (this.ifOnlyPingKongByReason) {
        this.pingKongByReason()
        this.pingKongByManualReason()
      }
      if (this.ifOnlyPingDuoByReason) {
        this.pingDuoByReason()
      }
      // 12
    } else {
      const sr = this.ifSellReverseTrend || this.ifSellPrePositiveTrend || this.ifSellPreReverseTrend
      const br = this.ifBuyReverseTrend || this.ifBuyPrePositiveTrend || this.ifBuyPreReverseTrend
      this.pingDuoIfMarketInfo()
      this.pingDuoIfMacdUpManyDaysDown()
      this.pingDuoIfNowTopHigh()
      this.pingDuoIfNowBigDown()
      this.pingDuoIfKdjTrans()
      this.pingDuoReversePosition()
      this.pingDuoIfProfitReduce()
      this.pingDuoByCanOpenMany()
      // ifSellReverseTrend和ifBuyReverseTrend的优先级很高，仅次于reason
      if (!sr && !br) {
        this.noBuyIfLineBad()
        this.noBuyIfMarketInfo()
        this.noBuyIfStatusBad()
      }
      this.pingKongIfMarketInfo()
      this.pingKongIfMacdDownManyDaysUp()
      this.pingKongIfNowDownHigh()
      this.pingKongIfKdjTrans()
      this.pingKongReversePosition()
      this.pingKongIfProfitReduce()
      this.pingKongByCanOpenMany()
      if (!sr && !br) {
        this.noSellIfNowDownHigh()
        this.noSellIfLineBad()
        this.noSellIfMarketInfo()
        this.noSellIfStatusGood()
      }
      this.noPingDuoIfAllBad()
      this.noPingKongIfAllGood()
      // 新高新低限制
      if (!sr && !br) {
        this.noSellIfNewHigh()
        this.noBuyIfNewLow()
      }
      // 仓位限制
      if (!sr && !br) {
        this.noBuyIfNoProfit()
        this.noSellIfNoProfit()
      }
      // 止损止盈
      this.pingDuoIfStopLoss()
      this.pingKongIfStopLoss()
      this.pingDuoIfProfitMany()
      this.pingKongIfProfitMany()

      // 特殊市场
      if (!sr && !br) {
        this.sellIfSpecialMarket()
        this.buyIfSpecialMarket()
        this.pingDuoIfSpecialMarket()
        this.pingKongIfSpecialMarket()
        this.noBuyIfSpecialMarket()
        this.noSellIfSpecialMarket()
        this.executeBySpecialMarket()
      }
    }
    this.pingDuoByConfig()
    this.pingKongByConfig()
    // this.pingDuoForce()
    // this.pingKongForce()
    this.pingDuoIfMarketOneDayUpMany()
    this.neverBuyIfLineBad()
    this.neverSellIfLineBad()
    // 找币不产生买卖信号
    this.ifCanAddPoolIfAttack15m()
    this.ifCanAddPoolIfOnlyKong()
    this.ifCanAddPoolIfOnlyDuo()
    this.ifCanAddPoolIfLikeKong()
    this.ifAddInPool()
    // 生成优先级
    this.buySellPriority = this.getBuySellPriority()
    this.reConfigBtbExecutePosition()
    // 天的数据太少
    if (
      !(this.marketFlagInfo.isMarketLittleGoodUp || this.marketFlagInfo.isMarketLittleBadDown) &&
      !this.analysisInfo1d.hasFullData
    ) {
      // 不要提升为变量，因为ifOnlyPingKongByReason的值是会变化的
      if (!(
        this.ifOnlyPingKongByReason || this.ifOnlyPingDuoByReason ||
        this.ifSellReverseTrend || this.ifSellPrePositiveTrend || this.ifSellPreReverseTrend ||
        this.ifBuyReverseTrend || this.ifBuyPrePositiveTrend || this.ifBuyPreReverseTrend
      )) {
        this.setNoExecuteRaw('noExecute-2')
      }
    }
  },
  resetAccount (config) {
    if (config.futuresAccount) {
      this.futuresAccount = config.futuresAccount
    }
    this.symbolAccount = config.symbolAccount
    this.btbItem.usdt = this.symbolAccount.notional || 0
    this.hasPosition = Math.abs(this.btbItem.usdt) > 2
    this.hasDuoPosition = this.hasPosition && this.btbItem.usdt > 0
    this.hasKongPosition = this.hasPosition && this.btbItem.usdt < 0
    if (this.hasPosition) {
      this.directionType = this.btbItem.usdt > 0 ? '多' : '空'
    } else {
      this.directionType = ''
      this.btbItem.ping_next_k = 0
      this.btbItem.ping_next_1hk = 0
      this.btbItem.add_times = 0
      this.btbItem.max_all15m_times = 0
    }
  },
  setBeforeSymbolAccount () {
    this.beforeSymbolAccount = {
      hasPosition: this.hasPosition,
      hasDuoPosition: this.hasDuoPosition,
      hasKongPosition: this.hasKongPosition,
      ...this.symbolAccount
    }
  },
  getQuantityParams () {
    let standardInitialMargin = this.symbolAccount.standardInitialMargin
    // 手动配置了最低仓位
    if (this.minPositionConfig && this.minPositionConfig > this.futuresAccount.positionConfig) {
      standardInitialMargin = this.minPositionConfig * this.symbolAccount.rawStandardInitialMargin
    }
    // 手动修改指数的仓位
    if (this.coverPositionConfig) {
      standardInitialMargin = this.coverPositionConfig * this.symbolAccount.rawStandardInitialMargin
    }
    // 不是hasFullData的会再重置一遍
    if (this.buySellRawTotalWalletBalance) {
      // 根据全仓来买卖
      standardInitialMargin = this.symbolAccount.rawStandardInitialMargin
      if (standardInitialMargin < (this.futuresAccount.rawTotalWalletBalance * 0.05)) {
        standardInitialMargin = (this.futuresAccount.rawTotalWalletBalance * 0.05)
      }
    }
    // 最大仓
    if (this.useMaxIndexBuySellPosition) {
      standardInitialMargin = this.symbolAccount.maxStandardInitialMargin
    }
    return {
      close: this.btbItem.close,
      // 修改这个金额，就可以买进更多
      standardInitialMargin: standardInitialMargin,
      rawStandardInitialMargin: this.symbolAccount.rawStandardInitialMargin,
      rawTotalWalletBalance: this.futuresAccount.rawTotalWalletBalance,
      leverage: this.btbLeverage,
      initialMargin: this.symbolAccount.initialMargin,
      usdt: this.symbolAccount.notional,
      availableBalance: this.futuresAccount.availableBalance,
      positionAmt: this.symbolAccount.positionAmt,
      trackList: this.trackList
    }
  },
  getBuySellConfigInfo () {
    return {
      usdtKey: this.btbItem.symbol,
      tradeTime15mCycle: this.tradeTime15mCycle,
      buy: this.buy,
      sell: this.sell,
      pingDuo: this.pingDuo && this.hasDuoPosition,
      pingKong: this.pingKong && this.hasKongPosition,
      pingDuoRaw: this.pingDuo,
      pingKongRaw: this.pingKong,
      buyRate: this.buyRate,
      sellRate: this.sellRate,
      pingDuoRate: this.pingDuoRate,
      pingKongRate: this.pingKongRate,
      strategy: this.strategy,
      strategy_result: this.strategyResult,
      trackList: this.trackList
    }
  },
  async requestOrder () {
    const info = {
      ...this.getBuySellConfigInfo(),
      ...this.getQuantityParams(),
      hasPosition: this.hasPosition,
      hasDuoPosition: this.hasDuoPosition,
      hasKongPosition: this.hasKongPosition
    }
    if (info.availableBalance < (info.rawTotalWalletBalance * 0.05)) {
      // 预留一部分的保证金
      info.availableBalance = 0
    }
    if (this.buy || this.sell || this.pingDuo || this.pingKong) {
      // 获取数量
      const val = quantityUtilHY.getQuantityV2(this.btbItem, info)
      const exParams = {
        usdtKey: this.btbItem.symbol,
        quantity: val,
        btbItem: this.btbItem,
        btbLeverage: this.btbLeverage
      }
      let requestResult = false
      try {
        if (this.buy) {
          requestResult = await this.requestBuyOrder(exParams)
          this.requestBuySellType = 'buy'
        } else if (this.sell) {
          requestResult = await this.requestSellOrder(exParams)
          this.requestBuySellType = 'sell'
        } else if (this.pingKong && this.hasKongPosition) {
          requestResult = await this.requestBuyOrder(exParams)
          this.requestBuySellType = 'pingKong'
        } else if (this.pingDuo && this.hasDuoPosition) {
          requestResult = await this.requestSellOrder(exParams)
          this.requestBuySellType = 'pingDuo'
        }
        if (requestResult) {
          this.requestOrderId = requestResult.orderId
          this.setBeforeSymbolAccount()
        }
        return requestResult
      } catch (e) {
        console.log(e)
        this.pushError(e)
        return false
      }
    }
    return false
  },
  // 执行买入
  async requestBuyOrder (exParams) {
    if (this.buy) {
      this.btbModelUpdateParams.direction_level = this.directionLevel
      // 更新原因记录，这里不需要实际的买入，因为可能会有
      this.btbReasonList = this.getBuyReasonResultList()
    }
    // 数量为0
    if (!exParams.quantity) {
      return false
    }
    const result = await binanceProxy.futuresMarketBuy(exParams)
    if (result) {
      this.btbModelUpdateParams.buySellQuantity = exParams.quantity
      this.btbModelUpdateParams.market_buy_order_id = result.orderId
      this.btbModelUpdateParams.market_sell_order_id = ''
      this.btbModelUpdateParams.strategy = this.strategy
      this.btbModelUpdateParams.strategy_result = this.strategyResult
      if (this.buy) {
        this.btbModelUpdateParams.direction = '多'
        if (this.ifCoverBtbBuySellReason()) {
          this.btbModelUpdateParams.buy_sell_reason = this.buyReason
        }
        this.tradeReason = this.buyReason
        this.btbModelUpdateParams.keep_days = 1
        this.btbModelUpdateParams.max_income_rate = 0
        this.manual = 0
      } else if (this.pingKong) {
        // 平仓啥也不更新
        this.tradeReason = this.pingKongReason
      }
    }
    return result
  },
  async requestSellOrder (exParams) {
    if (this.sell) {
      this.btbModelUpdateParams.direction_level = this.directionLevel
      // 更新原因记录，这里不需要实际的买入，因为可能会有
      this.btbReasonList = this.getSellReasonResultList()
    }
    // 数量为0
    if (!exParams.quantity) {
      return false
    }
    const result = await binanceProxy.futuresMarketSell(exParams)
    if (result) {
      this.btbModelUpdateParams.buySellQuantity = exParams.quantity
      this.btbModelUpdateParams.market_sell_order_id = result.orderId
      this.btbModelUpdateParams.market_buy_order_id = ''
      this.btbModelUpdateParams.strategy = this.strategy
      this.btbModelUpdateParams.strategy_result = this.strategyResult
      if (this.sell) {
        this.btbModelUpdateParams.direction = '空'
        if (this.ifCoverBtbBuySellReason()) {
          this.btbModelUpdateParams.buy_sell_reason = this.sellReason
        }
        this.tradeReason = this.sellReason
        this.btbModelUpdateParams.keep_days = 1
        this.btbModelUpdateParams.max_income_rate = 0
        this.manual = 0
      } else if (this.pingDuo) {
        // 平仓啥也不更新
        this.tradeReason = this.pingDuoReason
      }
    }
    return result
  },
  // 更新币的配置
  async requestUpdateBtbModel () {
    this.btbModelUpdateParams.ping_next_k = this.ifPingNextKlineLocal ? 1 : 0
    this.btbModelUpdateParams.ping_next_1hk = this.ifPingNext1hKlineLocal ? 1 : 0
    this.btbModelUpdateParams.leverage = this.btbLeverage || 1
    this.btbModelUpdateParams.manual = this.manual || 0
    // 持有天数更新
    if (!(this.requestOrderId && (this.sell || this.buy))) {
      // 没有新交易
      if (this.btbItem.keep_days) {
        this.btbModelUpdateParams.keep_days = this.btbItem.keep_days + 1
      }
    }
    // 最大的15all次数
    if (this.marketFlagInfo.market15mAllBadKeepDays > this.btbItem.max_all15m_times) {
      this.btbModelUpdateParams.max_all15m_times = this.marketFlagInfo.market15mAllBadKeepDays
    }
    if (this.marketFlagInfo.market15mAllGoodKeepDays > this.btbItem.max_all15m_times) {
      this.btbModelUpdateParams.max_all15m_times = this.marketFlagInfo.market15mAllGoodKeepDays
    }
    // 加仓次数更新
    this.btbModelUpdateParams.add_times = this.btbItem.add_times || 0
    if (
      (this.requestOrderId && this.sell && this.hasKongPosition) ||
      (this.requestOrderId && this.buy && this.hasDuoPosition)
    ) {
      this.btbModelUpdateParams.add_times = this.btbItem.add_times + 1
    }
    if (
      (this.requestOrderId && this.sell && this.hasDuoPosition) ||
      (this.requestOrderId && this.buy && this.hasKongPosition)
    ) {
      // 转向置为空
      this.btbModelUpdateParams.add_times = 0
    }
    this.btbModelUpdateParams.error_track = this.errorTrackList
    this.btbModelUpdateParams.reason_list = this.btbReasonList
    // 更新
    if (Object.keys(this.btbModelUpdateParams).length > 0) {
      await this.BtbIndexProxy.update({
        code: this.btbItem.code
      }, {
        ...this.btbModelUpdateParams,
        buy_sell_analysis_result: this.getBuySellConfigInfo()
      })
    }
  },
  // 止盈单
  async requestCancelStopOrder () {
    if (!this.hasPosition) {
      return
    }
    try {
      await binanceProxy.futuresCancelAll(this.btbItem.symbol)
      await this.BtbIndexProxy.update({
        code: this.btbItem.code
      }, {
        stop_profit_order_id: ''
      })
    } catch (e) {
      console.log(e)
      this.pushError(e)
    }
  },
  getDuoStopRate () {
    if (this.isBtbInReason('buyIfOnlyPingByReason-mbd-0003')) {
      return 2.5
    }
    if (this.isBtbInReason('buyIfOnlyPingByReason-mbd-0002')) {
      return 2
    }
    if (this.isBtbInReason('buyIfOnlyPingByReason-mbd-0001')) {
      return 2
    }
    let rate = 1.15
    if (this.ifOnlyPingDuoByReason) {
      return 1.4
    }
    if (this.marketFlagInfo.isMarketBigGoodUp) {
      return 1.30
    }
    if (
      (this.marketInfo.macd4hGood && this.marketInfo.ema4hGood) &&
      (this.marketInfo.macd1hGood && this.marketInfo.ema1hGood)
    ) {
      return 1.25
    }
    if (this.btbItem.price_change_percent >= 150) {
      return 1.25
    }
    if (
      (this.marketInfo.macd4hGood && this.marketInfo.ema4hGood) &&
      !(this.marketInfo.macd1hBad || this.marketInfo.ema1hBad)
    ) {
      return 1.2
    }
    if (this.btbItem.price_change_percent >= 100) {
      return 1.15
    }
    if (
      (this.marketInfo.macd4hBad && this.marketInfo.ema4hBad) &&
      !(this.marketInfo.macd1hGood || this.marketInfo.ema1hGood)
    ) {
      return 1.1
    }
    if (this.isDayChangeTime) {
      return 1.1
    }
    if (!(this.marketFlagInfo.ifMarket4hHasBad || this.marketFlagInfo.ifMarket4hHasGood)) {
      return 1.1
    }
    return rate
  },
  getKongStopRate () {
    let rate = 0.85
    if (this.ifOnlyPingKongByReason) {
      return 0.6
    }
    if (this.marketFlagInfo.isMarketBigBadDown) {
      return 0.7
    }
    if (
      (this.marketInfo.macd4hBad && this.marketInfo.ema4hBad) &&
      (this.marketInfo.macd1hBad && this.marketInfo.ema1hBad)
    ) {
      return 0.75
    }
    if (this.btbItem.price_change_percent >= 200) {
      return 0.75
    }
    if (
      (this.marketInfo.macd4hBad && this.marketInfo.ema4hBad) &&
      !(this.marketInfo.macd1hGood || this.marketInfo.ema1hGood)
    ) {
      return 0.8
    }
    if (this.btbItem.price_change_percent >= 100) {
      return 0.85
    }
    if (
      (this.marketInfo.macd4hGood && this.marketInfo.ema4hGood) &&
      !(this.marketInfo.macd1hBad || this.marketInfo.ema1hBad)
    ) {
      // 空单可以0.9
      return 0.9
    }
    if (this.isDayChangeTime) {
      return 0.9
    }
    if (!(this.marketFlagInfo.ifMarket4hHasBad || this.marketFlagInfo.ifMarket4hHasGood)) {
      return 0.9
    }
    return rate
  },
  async createStopOrder () {
    if (this.symbolAccount.positionAmt && this.symbolAccount.positionAmt < 0) {
      // 空单止盈，止损
      const info = {
        pingKong: true,
        ...this.getQuantityParams()
      }
      const val = quantityUtilHY.getQuantityV2(this.btbItem, info)
      if (val) {
        // -20%止盈
        let rate = this.getKongStopRate()
        let targetClose = this.stopClose ? this.stopClose : this.btbItem.close * rate
        const stopPrice = quantityUtilHY.formatPrice(
          targetClose,
          this.btbItem
        )
        this.stopProfitPrice = stopPrice
        try {
          const result = await binanceProxy.futuresBuy({
            usdtKey: this.btbItem.symbol,
            quantity: val,
            price: stopPrice
          })
          if (result) {
            await this.BtbIndexProxy.update({
              code: this.btbItem.code
            }, {
              stop_profit_order_id: result.orderId
            })
          }
        } catch (e) {
          this.pushError(e)
          console.log(e)
        }
      }
    } else if (this.symbolAccount.positionAmt && this.symbolAccount.positionAmt > 0) {
      // 多单止盈，止损
      const info = {
        pingDuo: true,
        ...this.getQuantityParams()
      }
      const val = quantityUtilHY.getQuantityV2(this.btbItem, info)
      if (val) {
        // -20%止盈
        let rate = this.getDuoStopRate()
        let targetClose = this.stopClose ? this.stopClose : this.btbItem.close * rate
        const stopPrice = quantityUtilHY.formatPrice(
          targetClose,
          this.btbItem
        )
        this.stopProfitPrice = stopPrice
        try {
          const result = await binanceProxy.futuresSell({
            usdtKey: this.btbItem.symbol,
            quantity: val,
            price: stopPrice
          })
          if (result) {
            await this.BtbIndexProxy.update({
              code: this.btbItem.code
            }, {
              stop_profit_order_id: result.orderId
            })
          }
        } catch (e) {
          this.pushError(e)
          console.log(e)
        }
      }
    }
  },
  async updateBtbPosition () {
    let data = {
      now_position_usdt: this.btbItem.usdt || 0,
      now_position_amt: this.symbolAccount.positionAmt || 0,
      stop_profit_price: this.stopProfitPrice || 0,
      now_position_cost_price: numberUtil.keepEightDecimals(this.symbolAccount.costPrice) || 0
    }
    const max_income_rate = this.btbItem.max_income_rate || 0
    if (this.symbolAccount.incomeRate > max_income_rate) {
      // 记录最大收益率
      data.max_income_rate = this.symbolAccount.incomeRate || 0
    }
    if (Math.abs(data.now_position_usdt) < 1.5) {
      // 没有仓位的及时腾出
      data = {
        ...data,
        status: 0,
        hy_status: 0,
        ...btbAs.getClearIndexConfigParams()
      }
    }
    await this.BtbIndexProxy.update({
      code: this.btbItem.code
    }, data)
  },
  async clearBtbPosition () {
    await this.BtbIndexProxy.update({
      code: this.btbItem.code
    }, {
      now_position_usdt: 0,
      now_position_amt: 0,
      now_position_cost_price: 0,
      stop_profit_price: 0,
      max_income_rate: 0,
      stop_profit_rate: 0
    })
  },
  setClosePositionParams () {
    if (this.symbolAccount.positionAmt && this.symbolAccount.positionAmt < 0) {
      this.pingKong = true
      this.pingKongReason = 'manual'
    } else if (this.symbolAccount.positionAmt && this.symbolAccount.positionAmt > 0) {
      this.pingDuo = true
      this.pingDuoReason = 'manual'
    }
  },
  // 获取买卖优先级
  getBuySellPriority () {
    if (!(this.buy || this.sell)) {
      return 0
    }
    // 配置的级别高
    if (this.ifOnlyPingDuoByReason || this.ifOnlyPingKongByReason) {
      if (this.directionLevel) {
        return this.directionLevel
      }
      return 100
    }
    if (this.buySellRawTotalWalletBalance) {
      return 9
    }
    if (this.directionLevel >= 10) {
      return 6
    }
    if (this.buyRate >= 1 || this.sellRate >= 1) {
      return 5
    }
    return 1
  },
  reConfigBtbExecutePosition () {
    if (!this.analysisInfo1d.hasFullData) {
      if (this.btbLeverage > 3) {
        this.btbLeverage = 3
      }
      // this.buySellRawTotalWalletBalance = false
      this.useMaxIndexBuySellPosition = false
      // this.coverPositionConfig = 0.5
    }
  },
  ...buyFunc,
  ...sellFunc,
  ...pingDuoFunc,
  ...pingKongFunc,
  ...addPoolFunc,
  ...noBuyFunc,
  ...noSellFunc,
  ...strategyFunc,
  ...analysisFindFunc,
  ...tradeRecordFunc,
  ...combinedIndicatorFunc,
  ...utilBuySellFunc,
  ...indexFlagFunc,
  ...noPingDuoFunc,
  ...noPingKongFunc,
  ...specialMarketFunc,
  ...sellReasonFunc,
  ...pingKongReasonFunc,
  ...sellReverseFunc,
  ...buyReasonFunc,
  ...buyReverseFunc,
  ...buyPreReverseFunc,
  ...buyPrePositiveFunc,
  ...sellPreReverseFunc,
  ...sellPrePositiveFunc,
  ...utilReasonFunc
}

module.exports = BuySellMachine
